package behaviorlearning;

import java.util.List;

import planninglanguage.plans.AttackBOPlan;
import planninglanguage.plans.AttackGroundBOPlan;
import planninglanguage.plans.BasicOperatorPlan;
import planninglanguage.plans.BuildBOPlan;
import planninglanguage.plans.MoveBOPlan;
import planninglanguage.plans.Plan;
import planninglanguage.plans.RepairBOPlan;
import planninglanguage.plans.ResearchBOPlan;
import planninglanguage.plans.ResourceBOPlan;
import planninglanguage.plans.ResourceLocationBOPlan;
import planninglanguage.plans.StopBOPlan;
import planninglanguage.plans.TrainBOPlan;
import planninglanguage.plans.UpgradeBOPlan;
import util.XMLWriter;
import base.WargusGameState;
import base.WargusMap;
import base.WargusPlayer;
import base.WargusStateImporter;
import base.WargusUnit;

public class WargusAction {
	private BasicOperatorPlan m_plan = null;	
	int m_unitID, m_destUnitID, m_x, m_y, m_playerID;
	private int m_constructedUnitID = -1;
	String m_action, m_value;
	WargusUnit m_u = null, m_du = null;
	
	public WargusAction(int playerID, int unitID, String unitType, String action,
			int x, int y, String value, int destUnitID, List<WargusPlayer> players) {
		m_action = action;
		m_playerID = playerID;
		m_x = x;
		m_y = y;
		m_value = value;
		m_unitID = unitID;
		m_destUnitID = destUnitID;
		
		if (action.equals("attack")) {
			if (destUnitID == -1) {
				m_plan = new AttackGroundBOPlan(unitID, x, y, null, null, null);
				m_action = "attack-loc";
			} else {
				m_plan = new AttackBOPlan(unitID, destUnitID, playerID, null, null, null);
			}
		} else if (action.equals("build")) {
			m_plan = new BuildBOPlan(unitID, x, y,
					WargusStateImporter.unitTypeToInteger(value.replaceFirst("unit-", "")),
					null, null, null);
			// XXX will this work b/c all values have unit- prefix  
		} else if (action.equals("move")) {
			m_plan = new MoveBOPlan(unitID, x, y , null, null, null);
		} else if (action.equals("repair")) {
			m_plan = new RepairBOPlan(unitID, destUnitID, null, null, null);
		} else if (action.equals("research")) {
			m_plan = new ResearchBOPlan(unitID, value, null, null, null);
		} else if (action.equals("resource")) {
			// needs to be converted to a ResourceLocationBOPlan later when we have a context
			m_plan = new ResourceBOPlan(unitID, destUnitID, null, null, null);
		} else if (action.equals("resource-loc")) {
			m_plan = new ResourceLocationBOPlan(unitID, x, y, null, null, null);
		} else if (action.equals("return")) {
			m_plan = null; // XXX we don't handle/care about return actions..
		} else if (action.equals("stop")) {
			m_plan = new StopBOPlan(unitID, null, null, null);
		} else if (action.equals("train")) {
			m_plan = new TrainBOPlan(unitID, 
					WargusStateImporter.unitTypeToInteger(value.replaceFirst("unit-", "")),
					null, null, null);
		} else if (action.equals("upgrade-to")) {
			m_plan = new UpgradeBOPlan(unitID, value.replaceFirst("unit-", ""),
					null, null, null);
		} else {
			throw new Error("Unsupported action type: " + action);
		}
		
		for(WargusPlayer p : players) {
			for(WargusUnit u : p.getUnits()) {
				if (u.getUnitID() == m_unitID) 
					m_u = u;
				else if (u.getUnitID() == m_destUnitID) 
					m_du = u;
			}
		}
		if (m_plan != null) {
			m_plan.setOriginalUnit(m_u);
			setTargetUnit();
		}		
	}
	
	private void setTargetUnit() {
		if (m_plan instanceof AttackBOPlan)
			((AttackBOPlan) m_plan).setOriginalTargetUnit(m_du);
		else if (m_plan instanceof RepairBOPlan)
			((RepairBOPlan) m_plan).setOriginalTargetUnit(m_du);
	}
	
	public void setConstructedUnitID(int i) {
		m_constructedUnitID = i;
		if (m_plan instanceof TrainBOPlan) {
			((TrainBOPlan) m_plan).setConstructedUnitID(i);
		} else if (m_plan instanceof BuildBOPlan) {
			((BuildBOPlan) m_plan).setConstructedUnitID(i);
		} else {
			throw new Error("Setting constructed unit id on unsupported action/plan type!");
		}
	}
	public int getConstructedUnitID() {
		return m_constructedUnitID;
	}
	
	public void update_units(List<WargusPlayer> players,WargusMap map) {
		// why where these null?
		//m_u = null;
		//m_du = null;
					
		for(WargusPlayer p : players) {
			for(WargusUnit u : p.getUnits()) {
				if (u.getUnitID() == m_unitID) 
					m_u = u;
				else if (u.getUnitID() == m_destUnitID) 
					m_du = u;
			}
		}		
		for(WargusUnit u : map.get_goldMines()) {
			if (u.getUnitID() == m_unitID) 
				m_u = u;
			else if (u.getUnitID() == m_destUnitID) 
				m_du = u;
		}
		for(WargusUnit u : map.get_oilPatches()) {
			if (u.getUnitID() == m_unitID) 
				m_u = u;
			else if (u.getUnitID() == m_destUnitID) 
				m_du = u;
		}
		
		if (m_plan != null) {
			m_plan.setOriginalUnit(m_u);
			setTargetUnit();
		}
	}
	
	public void setContext(WargusGameState context) {
		if (m_plan instanceof ResourceBOPlan) {
			// XXX ewww but idk what else to do to make it cleaner..
			WargusUnit resource = context.getUnit(
					((ResourceBOPlan) m_plan).getResourceType());
			//System.err.println("OOO: converted resourceplan: " + m_plan);
			m_plan = new ResourceLocationBOPlan(m_plan.getUnitID(), 
					resource.getLocX(), resource.getLocY(), null, null, null);
			// make a resourceLoc constructor that takes a ResourceBOP..
			m_plan.setOriginalUnit(m_u);
			m_du = resource;
			setTargetUnit();
			//System.err.println("OOO: to: " + m_plan);
			//if (m_plan.getUnitID() == -1) System.err.println("OOO: unitID == -1!");
		}
		m_plan.setContext(context);
	}
	
	public void writeXML(XMLWriter w) {
		m_plan.writeXML(w);
	}
	
	public Plan getPlan() {
		return m_plan;
	}
	
	public String toString() {
		String tmp = "";
		
		tmp = tmp + m_action + " ";
		
		try {
			if (m_u!=null) tmp += WargusStateImporter.unitTypeToString(m_u.getType()) + " ";
			if (m_x!=-1) tmp += m_x + " ";
			if (m_y!=-1) tmp += m_y + " ";
			if (m_value!=null) {
				if (m_value.startsWith("unit")) {
					tmp += m_value.substring("unit".length() + 1) + " ";
				} else {
					tmp += m_value + " ";
				}				
			}	
			if (m_du!=null) tmp = tmp + WargusStateImporter.unitTypeToString(m_du.getType()) + " ";	
		} catch (Exception e) {
			e.printStackTrace();
		}		

		return tmp;
	}	
}
